﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Giant.Core;
using Giant.Core.Data;
using Giant.Core.Domain;
using Giant.Core.Domain.Blogs;
using Giant.Core.Domain.Cms;
using Giant.Core.Domain.Common;
using Giant.Core.Domain.Users;
using Giant.Core.Domain.Localization;
using Giant.Core.Domain.Logging;
using Giant.Core.Domain.Media;
using Giant.Core.Domain.Messages;
using Giant.Core.Domain.News;
using Giant.Core.Domain.Security;
using Giant.Core.Domain.Seo;
using Giant.Core.Domain.Sites;
using Giant.Core.Domain.Tasks;
using Giant.Core.Domain.Topics;
using Giant.Core.Infrastructure;
using Giant.Services.Common;
using Giant.Services.Configuration;
using Giant.Services.Users;
using Giant.Services.Helpers;
using Giant.Services.Localization;
using Giant.Services.Media;
using Giant.Services.Seo;

namespace Giant.Services.Installation
{
    public partial class CodeFirstInstallationService : IInstallationService
    {
        #region Fields

        private readonly IRepository<Site> _siteRepository;
        private readonly IRepository<Language> _languageRepository;
        private readonly IRepository<User> _userRepository;
        private readonly IRepository<UserRole> _userRoleRepository;
        private readonly IRepository<UrlRecord> _urlRecordRepository;
        private readonly IRepository<EmailAccount> _emailAccountRepository;
        private readonly IRepository<MessageTemplate> _messageTemplateRepository;
        private readonly IRepository<Topic> _topicRepository;
        private readonly IRepository<BlogPost> _blogPostRepository;
        private readonly IRepository<NewsItem> _newsItemRepository;
        private readonly IRepository<ActivityLogType> _activityLogTypeRepository;
        private readonly IRepository<ActivityLog> _activityLogRepository;
        private readonly IRepository<TopicTemplate> _topicTemplateRepository;
        private readonly IRepository<ScheduleTask> _scheduleTaskRepository;
        private readonly IGenericAttributeService _genericAttributeService;
        private readonly IWebHelper _webHelper;

        #endregion

        #region Ctor

        public CodeFirstInstallationService(IRepository<Site> siteRepository,
            IRepository<Language> languageRepository,
            IRepository<User> userRepository,
            IRepository<UserRole> userRoleRepository,
            IRepository<UrlRecord> urlRecordRepository,
            IRepository<EmailAccount> emailAccountRepository,
            IRepository<MessageTemplate> messageTemplateRepository,
            IRepository<Topic> topicRepository,
            IRepository<BlogPost> blogPostRepository,
            IRepository<NewsItem> newsItemRepository,
            IRepository<ActivityLogType> activityLogTypeRepository,
            IRepository<ActivityLog> activityLogRepository,
            IRepository<TopicTemplate> topicTemplateRepository,
            IRepository<ScheduleTask> scheduleTaskRepository,
            IGenericAttributeService genericAttributeService,
            IWebHelper webHelper)
        {
            this._siteRepository = siteRepository;
            this._languageRepository = languageRepository;
            this._userRepository = userRepository;
            this._userRoleRepository = userRoleRepository;
            this._urlRecordRepository = urlRecordRepository;
            this._emailAccountRepository = emailAccountRepository;
            this._messageTemplateRepository = messageTemplateRepository;
            this._topicRepository = topicRepository;
            this._blogPostRepository = blogPostRepository;
            this._newsItemRepository = newsItemRepository;
            this._activityLogTypeRepository = activityLogTypeRepository;
            this._activityLogRepository = activityLogRepository;
            this._topicTemplateRepository = topicTemplateRepository;
            this._scheduleTaskRepository = scheduleTaskRepository;
            this._genericAttributeService = genericAttributeService;
            this._webHelper = webHelper;
        }

        #endregion

        #region Utilities

        protected virtual void InstallSites()
        {
            //var siteUrl = "http://www.yoursite.com/";
            var siteUrl = _webHelper.GetSiteLocation(false);
            var sites = new List<Site>
            {
                new Site
                {
                    Name = "巨人快速开发框架",
                    Url = siteUrl,
                    SslEnabled = false,
                    Hosts = "giantsoft.cn,www.giantsoft.cn",
                    DisplayOrder = 1,
                    //should we set some default company info?
                    CompanyName = "GiantSoft",
                    CompanyAddress = "",
                    CompanyPhoneNumber = "",
                },
            };

            _siteRepository.Insert(sites);
        }

        protected virtual void InstallLanguages()
        {
            var chinese = new Language
            {
                Name = "中文",
                LanguageCulture = "zh-CN",
                UniqueSeoCode = "cn",
                FlagImageFileName = "cn.png",
                Published = true,
                DisplayOrder = 1
            };
            _languageRepository.Insert(chinese);

            var english = new Language
            {
                Name = "English",
                LanguageCulture = "en-US",
                UniqueSeoCode = "en",
                FlagImageFileName = "us.png",
                Published = true,
                DisplayOrder = 1
            };
            _languageRepository.Insert(english);


        }

        protected virtual void InstallLocaleResources()
        {
            var languages = _languageRepository.Table.ToList();
            var files = System.IO.Directory.EnumerateFiles(CommonHelper.MapPath("~/App_Data/Localization/"), "*.res.xml", SearchOption.TopDirectoryOnly);

            foreach (var language in languages)
            {
                foreach (var filePath in files.Where(x => x.Contains(language.Name)))
                {
                    var localesXml = File.ReadAllText(filePath);
                    var localizationService = EngineContext.Current.Resolve<ILocalizationService>();
                    localizationService.ImportResourcesFromXml(language, localesXml);
                }
            }

            //save resources
        }
        
        protected virtual void InstallUsersAndUsers(string defaultUserEmail, string defaultUserPassword)
        {
            var crAdministrators = new UserRole
            {
                Name = "系统管理员",
                Active = true,
                IsSystemRole = true,
                SystemName = SystemUserRoleNames.Administrators,
            };
            var crRegistered = new UserRole
            {
                Name = "注册用户",
                Active = true,
                IsSystemRole = true,
                SystemName = SystemUserRoleNames.Registered,
            };
            var crGuests = new UserRole
            {
                Name = "访客",
                Active = true,
                IsSystemRole = true,
                SystemName = SystemUserRoleNames.Guests,
            };
           
            var userRoles = new List<UserRole>
                                {
                                    crAdministrators,
                                    crRegistered,
                                    crGuests
                                };
            _userRoleRepository.Insert(userRoles);

            //admin user
            var adminUser = new User
            {
                UserGuid = Guid.NewGuid(),
                Email = defaultUserEmail,
                Username = defaultUserEmail,
                Password = defaultUserPassword,
                PasswordFormat = PasswordFormat.Clear,
                PasswordSalt = "",
                Active = true,
                CreatedOnUtc = DateTime.UtcNow,
                LastActivityDateUtc = DateTime.UtcNow,
            };
            

            adminUser.UserRoles.Add(crAdministrators);
            adminUser.UserRoles.Add(crRegistered);
            _userRepository.Insert(adminUser);
            //set default user name
            _genericAttributeService.SaveAttribute(adminUser, SystemUserAttributeNames.FirstName, "Bill");
            _genericAttributeService.SaveAttribute(adminUser, SystemUserAttributeNames.LastName, "Gates");


            //second user
            var secondUserEmail = "steve_gates@giantsoft.cn";
            var secondUser = new User
            {
                UserGuid = Guid.NewGuid(),
                Email = secondUserEmail,
                Username = secondUserEmail,
                Password = "123456",
                PasswordFormat = PasswordFormat.Clear,
                PasswordSalt = "",
                Active = true,
                CreatedOnUtc = DateTime.UtcNow,
                LastActivityDateUtc = DateTime.UtcNow,
            };
           
            secondUser.UserRoles.Add(crRegistered);
            _userRepository.Insert(secondUser);


            //third user
            var thirdUserEmail = "arthur_holmes@giantsoft.cn";
            var thirdUser = new User
            {
                UserGuid = Guid.NewGuid(),
                Email = thirdUserEmail,
                Username = thirdUserEmail,
                Password = "123456",
                PasswordFormat = PasswordFormat.Clear,
                PasswordSalt = "",
                Active = true,
                CreatedOnUtc = DateTime.UtcNow,
                LastActivityDateUtc = DateTime.UtcNow,
            };
          
            thirdUser.UserRoles.Add(crRegistered);
            _userRepository.Insert(thirdUser);

            
            //fourth user
            var fourthUserEmail = "james_pan@giantsoft.cn";
            var fourthUser = new User
            {
                UserGuid = Guid.NewGuid(),
                Email = fourthUserEmail,
                Username = fourthUserEmail,
                Password = "123456",
                PasswordFormat = PasswordFormat.Clear,
                PasswordSalt = "",
                Active = true,
                CreatedOnUtc = DateTime.UtcNow,
                LastActivityDateUtc = DateTime.UtcNow,
            };

            fourthUser.UserRoles.Add(crRegistered);
            _userRepository.Insert(fourthUser);


            //fifth user
            var fifthUserEmail = "brenda_lindgren@giantsoft.cn";
            var fifthUser = new User
            {
                UserGuid = Guid.NewGuid(),
                Email = fifthUserEmail,
                Username = fifthUserEmail,
                Password = "123456",
                PasswordFormat = PasswordFormat.Clear,
                PasswordSalt = "",
                Active = true,
                CreatedOnUtc = DateTime.UtcNow,
                LastActivityDateUtc = DateTime.UtcNow,
            };

            fifthUser.UserRoles.Add(crRegistered);
            _userRepository.Insert(fifthUser);


            //sixth user
            var sixthUserEmail = "victoria_victoria@giantsoft.cn";
            var sixthUser = new User
            {
                UserGuid = Guid.NewGuid(),
                Email = sixthUserEmail,
                Username = sixthUserEmail,
                Password = "123456",
                PasswordFormat = PasswordFormat.Clear,
                PasswordSalt = "",
                Active = true,
                CreatedOnUtc = DateTime.UtcNow,
                LastActivityDateUtc = DateTime.UtcNow,
            };

            sixthUser.UserRoles.Add(crRegistered);
            _userRepository.Insert(sixthUser);


            //search engine (crawler) built-in user
            var searchEngineUser = new User
            {
                Email = "builtin@search_engine_record.com",
                UserGuid = Guid.NewGuid(),
                PasswordFormat = PasswordFormat.Clear,
                AdminComment = "Built-in system guest record used for requests from search engines.",
                Active = true,
                IsSystemAccount = true,
                SystemName = SystemUserNames.SearchEngine,
                CreatedOnUtc = DateTime.UtcNow,
                LastActivityDateUtc = DateTime.UtcNow,
            };
            searchEngineUser.UserRoles.Add(crGuests);
            _userRepository.Insert(searchEngineUser);


            //built-in user for background tasks
            var backgroundTaskUser = new User
            {
                Email = "builtin@background-task-record.com",
                UserGuid = Guid.NewGuid(),
                PasswordFormat = PasswordFormat.Clear,
                AdminComment = "Built-in system record used for background tasks.",
                Active = true,
                IsSystemAccount = true,
                SystemName = SystemUserNames.BackgroundTask,
                CreatedOnUtc = DateTime.UtcNow,
                LastActivityDateUtc = DateTime.UtcNow,
            };
            backgroundTaskUser.UserRoles.Add(crGuests);
            _userRepository.Insert(backgroundTaskUser);
        }

        protected virtual void HashDefaultUserPassword(string defaultUserEmail, string defaultUserPassword)
        {
            var userRegistrationService = EngineContext.Current.Resolve<IUserRegistrationService>();
            userRegistrationService.ChangePassword(new ChangePasswordRequest(defaultUserEmail, false,
                 PasswordFormat.Hashed, defaultUserPassword));
        }

        protected virtual void InstallEmailAccounts()
        {
            var emailAccounts = new List<EmailAccount>
                               {
                                   new EmailAccount
                                       {
                                           Email = "test@mail.com",
                                           DisplayName = "Site name",
                                           Host = "smtp.mail.com",
                                           Port = 25,
                                           Username = "123",
                                           Password = "123",
                                           EnableSsl = false,
                                           UseDefaultCredentials = false
                                       },
                               };
            _emailAccountRepository.Insert(emailAccounts);
        }

        protected virtual void InstallMessageTemplates()
        {
            var eaGeneral = _emailAccountRepository.Table.FirstOrDefault();
            if (eaGeneral == null)
                throw new Exception("Default email account cannot be loaded");
            var messageTemplates = new List<MessageTemplate>
                               {
                                   new MessageTemplate
                                       {
                                           Name = "Blog.BlogComment",
                                           Subject = "%Site.Name%. New blog comment.",
                                           Body = "<p><a href=\"%Site.URL%\">%Site.Name%</a> <br /><br />A new blog comment has been created for blog post \"%BlogComment.BlogPostTitle%\".</p>",
                                           IsActive = true,
                                           EmailAccountId = eaGeneral.Id,
                                       },
                                  
                                   new MessageTemplate
                                       {
                                           Name = "User.EmailValidationMessage",
                                           Subject = "%Site.Name%. 邮箱验证",
                                           Body = "<a href=\"%Site.URL%\">%Site.Name%</a>  <br />  <br /> 激活账号， <a href=\"%User.AccountActivationURL%\">请点我</a>.     <br />  <br />  %Site.Name%",
                                           IsActive = true,
                                           EmailAccountId = eaGeneral.Id,
                                       },                                  
                                   new MessageTemplate
                                       {
                                           Name = "User.PasswordRecovery",
                                           Subject = "%Site.Name%. 密码恢复",
                                           Body = "<a href=\"%Site.URL%\">%Site.Name%</a>  <br />  <br />  更改密码， <a href=\"%User.PasswordRecoveryURL%\">请点我</a>.     <br />  <br />  %Site.Name%",
                                           IsActive = true,
                                           EmailAccountId = eaGeneral.Id,
                                       },
                                   new MessageTemplate
                                       {
                                           Name = "User.WelcomeMessage",
                                           Subject = "欢迎访问 %Site.Name%",
                                           Body = "欢迎访问 <a href=\"%Site.URL%\"> %Site.Name%</a>.<br /><br />如果您有任何问题, 请发邮件给网站管理员: <a href=\"mailto:%Site.Email%\">%Site.Email%</a>.<br /><br />",
                                           IsActive = true,
                                           EmailAccountId = eaGeneral.Id,
                                       },
                                  
                                   new MessageTemplate
                                       {
                                           Name = "NewUser.Notification",
                                           Subject = "%Site.Name%. 新用户注册",
                                           Body = "<p><a href=\"%Site.URL%\">%Site.Name%</a> <br /><br />新用户注册，以下是用户详情：<br />Full name: %User.FullName%<br />Email: %User.Email%</p>",
                                           IsActive = true,
                                           EmailAccountId = eaGeneral.Id,
                                       },
                                  
                                   new MessageTemplate
                                       {
                                           Name = "News.NewsComment",
                                           Subject = "%Site.Name%. 收到新闻评论.",
                                           Body = "<p><a href=\"%Site.URL%\">%Site.Name%</a> <br /><br />收到一条新闻评论，在 \"%NewsComment.NewsTitle%\".</p>",
                                           IsActive = true,
                                           EmailAccountId = eaGeneral.Id,
                                       }                                 
                                  
                               };
            _messageTemplateRepository.Insert(messageTemplates);
        }

        protected virtual void InstallTopics()
        {
            var defaultTopicTemplate =
                _topicTemplateRepository.Table.FirstOrDefault(tt => tt.Name == "Default template");
            if (defaultTopicTemplate == null)
                throw new Exception("Topic template cannot be loaded");

            var topics = new List<Topic>
                               {
                                    new Topic
                                       {
                                           SystemName = "HomePageText",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           DisplayOrder = 1,
                                           Published = true,
                                           Title = "欢迎访问",
                                           Body = "<h1>巨人快速开发框架</h1> <p> 基于.NET的开发框架，全开源，简单易用，帮助您快速搭建各类信息管理系统<br> 适用于个人开发者及小型软件公司 </p>",
                                           TopicTemplateId = defaultTopicTemplate.Id,
                                           MetaTitle = "巨人ASP.NET MVC框架",
                                           MetaKeywords="MVC,ASP.NET MVC,快速开发框架",
                                           MetaDescription = "巨人ASP.NET MVC快速开发框架"
                                       },
                                   new Topic
                                       {
                                           SystemName = "About",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           IncludeInFooterColumn1 = true,
                                           DisplayOrder = 20,
                                           Published = true,
                                           Title = "关于",
                                           Body = "<h3>什么是快速开发框架？</h3> <p>快速开发框架，顾名思义就是提供了一般软件项目所必须的基础功能，如ORM、依赖注入等， 从而减少代码量，使开发者专注于业务需求，提高工作效率，达到快速开发的目的。</p>"+
                                           "<h3>为什么选择巨人快速开发框架？</h3> <p>巨人快速开发框架是在多个优秀的开源项目基础之上，如Entity Framework、Autofac等，结合实际的软件需求，"+
                                           " 提炼出的一款开发框架。除了上述基础功能，巨人快速开发框架还实现了用户管理、角色权限管理、缓存、日志、数据库备份等功能。同时，支持多语言和插件式开发。 巨人快速开发框架适用于OA、信息管理、电子政务、电子商务、CRM等基于B/S架构的应用软件系统。</p>",
                                           TopicTemplateId = defaultTopicTemplate.Id
                                       },                                  
                                   new Topic
                                       {
                                           SystemName = "ConditionsOfUse",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           IncludeInFooterColumn1 = false,
                                           DisplayOrder = 15,
                                           Published = true,
                                           Title = "使用说明",
                                           Body = "<p>请您联系我们索取使用帮助</p>",
                                           TopicTemplateId = defaultTopicTemplate.Id
                                       },
                                   new Topic
                                       {
                                           SystemName = "ContactUs",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           DisplayOrder = 1,
                                           Published = true,
                                           Title = "留言",
                                           Body = "<h1>巨人快速开发框架</h1><p></p>",
                                           TopicTemplateId = defaultTopicTemplate.Id,
                                           MetaTitle = "如何获取巨人快速开发框架源代码",
                                           MetaKeywords="源代码下载",
                                           MetaDescription = "下载巨人ASP.NET MVC快速开发框架源代码"
                                       },
                                    new Topic
                                       {
                                           SystemName = "Contact",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           DisplayOrder = 1,
                                           Published = true,
                                           Title = "联系方式",
                                           Body = "<h2 class=\"centered\">联系方式</h2> <hr> <div class=\"col-md-4 centered\"> <i class=\"fa fa-envelope-o fa-2x\"></i> <p>qiaoxw@giantsoft.cn</p> "+
                                           "</div> <div class=\"col-md-4\"> <i class=\"fa fa-wechat fa-2x\"></i> <br> <img src=\"/content/images/wechat.jpg\" alt=\"微信\" /> </div> "+
                                           "<div class=\"col-md-4\"> <i class=\"fa  fa-qq fa-2x\"></i> <br> <img src=\"/content/images/qq.jpg\" alt=\"QQ\" /> </div>",
                                           TopicTemplateId = defaultTopicTemplate.Id
                                       },
                                    new Topic
                                       {
                                           SystemName = "Services",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           DisplayOrder = 1,
                                           Published = true,
                                           Title = "功能特点",
                                           Body = "<h2 class=\"centered\">功能特点</h2> <hr> <div class=\"col-lg-8 col-lg-offset-2\">"+
                                           " <p class=\"large\">GiantSoft一直致力于为.NET开发者提供高效、易用的快速开发框架。如果您对本项目有任何意见或建议，欢迎您随时联系我们，非常感谢。</p>"+
                                           " </div> <div class=\"col-lg-3 callout\"> <i class=\"fa fa-desktop fa-3x\"></i> <h3>完善的功能</h3> "+
                                           "<p>集成用户管理、角色权限管理、缓存、日志、数据库备份等基础功能，支持多语言</p> </div> "+
                                           "<div class=\"col-lg-3 callout\"> <i class=\"fa fa-plug  fa-3x\"></i> <h3>插件式开发</h3>"+
                                           " <p>支持插件安装配置，您可以按照需求开发插件，扩展系统功能</p> </div> <div class=\"col-lg-3 callout\"> <i class=\"fa fa-users fa-3x\"></i>"+
                                           " <h3>开源的代码</h3> <p>所有代码全部开源，允许被许可人发布经过修改的代码，让您后顾之忧</p> </div> <div class=\"col-lg-3 callout\"> "+
                                           "<i class=\"fa fa-gears fa-3x\"></i> <h3>可靠的质量</h3> <p>对于已实现的功能，提供了多达200余个单元测试，有效的保证了代码质量</p> </div>",
                                           TopicTemplateId = defaultTopicTemplate.Id,
                                           
                                       },
                                   
                                   new Topic
                                       {
                                           SystemName = "LoginRegistrationInfo",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           DisplayOrder = 1,
                                           Published = true,
                                           Title = "",
                                           Body = "<p></p>",
                                           TopicTemplateId = defaultTopicTemplate.Id
                                       },
                                   new Topic
                                       {
                                           SystemName = "PrivacyInfo",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           IncludeInFooterColumn1 = false,
                                           DisplayOrder = 10,
                                           Published = false,
                                           Title = "Privacy notice",
                                           Body = "<p>Put your privacy policy information here. You can edit this in the admin site.</p>",
                                           TopicTemplateId = defaultTopicTemplate.Id
                                       },
                                   new Topic
                                       {
                                           SystemName = "PageNotFound",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           DisplayOrder = 1,
                                           Published = true,
                                           Title = "",
                                           Body = "<p><strong>您所请求的页面没有找到，请检查您所输入的访问地址是否正确</strong></p><ul><li>非常抱歉，您访问的页面不存在，请尝试访问其它链接</li></ul>",
                                           TopicTemplateId = defaultTopicTemplate.Id
                                       },
                                    new Topic
                                       {
                                           SystemName = "HomePagePortfolio",
                                           IncludeInSitemap = false,
                                           IsPasswordProtected = false,
                                           DisplayOrder = 1,
                                           Published = true,
                                           Title = "系统演示",
                                           Body = "<div<div class=\"row\"> <h2 class=\"centered\">框架展示</h2> <hr> "+
                                           "<div class=\"col-lg-8 col-lg-offset-2 centered\"> <p class=\"large\">"+
                                           "以下是巨人快速开发框架部分页面展示， 您也可以通过本站提供的<a href=\"demo.giantsoft.cn\" target=\"_blank\">Demo</a>进行体验</p>"+
                                           "</div> </div> <div class=\"container\"> <div class=\"row\"> <div class=\"col-md-4\"> <div class=\"grid mask\">"+
                                           "<figure> <img class=\"img-responsive\" src=\"/content/images/portfolio/folio01.jpg\" alt=\"\"> <figcaption>"+
                                           "<h5>系统前台</h5> <a data-toggle=\"modal\" href=\"#myModal\" class=\"btn btn-default\" data-title=\"系统前台展示\" data-picture=\"/content/images/portfolio/folio01-preview.jpg\" data-url=\"http://demo.giantsoft.cn\">更多</a> </figcaption> </figure> </div> </div>"+
                                           "<div class=\"col-md-4\"> <div class=\"grid mask\"> <figure> <img class=\"img-responsive\" src=\"/content/images/portfolio/folio02.jpg\" alt=\"\"> "+
                                           "<figcaption> <h5>系统后台</h5> <a data-toggle=\"modal\" href=\"#myModal\" class=\"btn btn-default\" data-title=\"系统后台展示\" data-picture=\"/content/images/portfolio/folio02-preview.jpg\" data-url=\"http://demo.giantsoft.cn\">更多</a> </figcaption> </figure> </div> </div> "+
                                           "<div class=\"col-md-4\"> <div class=\"grid mask\"> <figure> <img class=\"img-responsive\" src=\"/content/images/portfolio/folio03.jpg\" alt=\"\"> <figcaption> <h5>代码结构</h5>"+
                                           "<a data-toggle=\"modal\" href=\"#myModal\" class=\"btn btn-default\" data-title=\"代码结构展示\" data-picture=\"/content/images/portfolio/folio03-preview.jpg\" data-url=\"http://demo.giantsoft.cn\">更多</a> </figcaption> </figure> </div> </div> </div> </div> ",
                                           TopicTemplateId = defaultTopicTemplate.Id
                                       },
                               };
            _topicRepository.Insert(topics);


            //search engine names
            foreach (var topic in topics)
            {
                _urlRecordRepository.Insert(new UrlRecord
                {
                    EntityId = topic.Id,
                    EntityName = "Topic",
                    LanguageId = 0,
                    IsActive = true,
                    Slug = topic.ValidateSeName("", !String.IsNullOrEmpty(topic.Title) ? topic.Title : topic.SystemName, true)
                });
            }

        }

        protected virtual void InstallSettings()
        {
            var settingService = EngineContext.Current.Resolve<ISettingService>();
            
            settingService.SaveSetting(new CommonSettings
            {
                UseSystemEmailForContactUsForm = true,
                UseStoredProceduresIfSupported = true,
                SitemapEnabled = true,
                DisplayJavaScriptDisabledWarning = false,
                Log404Errors = true,
                BreadcrumbDelimiter = "/",
                RenderXuaCompatible = false,
                XuaCompatibleValue = "IE=edge"
            });

            settingService.SaveSetting(new SeoSettings
            {
                PageTitleSeparator = ". ",
                PageTitleSeoAdjustment = PageTitleSeoAdjustment.PagenameAfterSitename,
                DefaultTitle = "巨人快速开发框架",
                DefaultMetaKeywords = "",
                DefaultMetaDescription = "",
                ConvertNonWesternChars = false,
                AllowUnicodeCharsInUrls = true,
                CanonicalUrlsEnabled = false,
                WwwRequirement = WwwRequirement.NoMatter,
                //we disable bundling out of the box because it requires a lot of server resources
                EnableJsBundling = false,
                EnableCssBundling = false,
                OpenGraphMetaTags = true,
                ReservedUrlRecordSlugs = new List<string>
                    {
                        "admin",
                        "install",               
                        "login",
                        "register",
                        "contactus",
                        "passwordrecovery",
                        "subscribenewsletter",
                        "blog",
                        "news",
                        "sitemap",
                        "config",
                        "page-not-found"
                    },
                CustomHeadTags = "",
            });

            settingService.SaveSetting(new AdminAreaSettings
            {
                DefaultGridPageSize = 15,
                PopupGridPageSize = 10,
                GridPageSizes = "10, 15, 20, 50, 100",
                RichEditorAdditionalSettings = null,
                RichEditorAllowJavaScript = false
            });

            settingService.SaveSetting(new LocalizationSettings
            {
                DefaultAdminLanguageId = _languageRepository.Table.Single(l => l.Name == "中文").Id,
                UseImagesForLanguageSelection = false,
                SeoFriendlyUrlsForLanguagesEnabled = false,
                AutomaticallyDetectLanguage = false,
                LoadAllLocaleRecordsOnStartup = true,
                LoadAllLocalizedPropertiesOnStartup = true,
                LoadAllUrlRecordsOnStartup = false,
                IgnoreRtlPropertyForAdminArea = false
            });

            settingService.SaveSetting(new UserSettings
            {
                UsernamesEnabled = false,
                CheckUsernameAvailabilityEnabled = false,
                AllowUsersToChangeUsernames = false,
                DefaultPasswordFormat = PasswordFormat.Hashed,
                HashedPasswordFormat = "SHA1",
                PasswordMinLength = 6,
                PasswordRecoveryLinkDaysValid = 7,
                UserRegistrationType = UserRegistrationType.Disabled,
                AllowUsersToUploadAvatars = false,
                AvatarMaximumSizeBytes = 20000,
                DefaultAvatarEnabled = true,
                ShowUsersJoinDate = false,
                AllowViewingProfiles = false,
                NotifyNewUserRegistration = false,
                UserNameFormat = UserNameFormat.ShowFirstName,
                GenderEnabled = true,
                DateOfBirthEnabled = true,
                DateOfBirthRequired = false,
                DateOfBirthMinimumAge = null,             
                PhoneEnabled = false,
                AcceptPrivacyPolicyEnabled = false,
                NewsletterEnabled = true,
                NewsletterTickedByDefault = true,
                HideNewsletterBlock = false,
                NewsletterBlockAllowToUnsubscribe = false,
                OnlineUserMinutes = 20,
                SiteLastVisitedPage = false,
                SuffixDeletedUsers = false,
                EnteringEmailTwice = false,
                DeleteGuestTaskOlderThanMinutes = 1440
            });
            
            settingService.SaveSetting(new MediaSettings
            {
                AvatarPictureSize = 120,             
                MaximumImageSize = 1980,
                DefaultPictureZoomEnabled = false,
                DefaultImageQuality = 80,
                MultipleThumbDirectories = false
            });

            settingService.SaveSetting(new SiteInformationSettings
            {
                SiteClosed = false,
                DefaultSiteTheme = "Ascend",
                AllowUserToSelectTheme = false,
                DisplayMiniProfilerInPublicSite = false,
                HidePoweredByGiantSoft = false
            });

            settingService.SaveSetting(new ExternalAuthenticationSettings
            {
                AutoRegisterEnabled = true,
                RequireEmailValidation = false
            });         

            settingService.SaveSetting(new MessageTemplatesSettings
            {
                CaseInvariantReplacement = false,
                Color1 = "#b9babe",
                Color2 = "#ebecee",
                Color3 = "#dde2e6",
            });           

            settingService.SaveSetting(new SecuritySettings
            {
                ForceSslForAllPages = false,
                EncryptionKey = CommonHelper.GenerateRandomDigitCode(16),
                AdminAreaAllowedIpAddresses = null,
                EnableXsrfProtectionForAdminArea = true,
                EnableXsrfProtectionForPublicSite = true,
                HoneypotEnabled = false,
                HoneypotInputName = "hpinput"
            });
            
            settingService.SaveSetting(new DateTimeSettings
            {
                DefaultSiteTimeZoneId = "",
                AllowUsersToSetTimeZone = false
            });

            settingService.SaveSetting(new BlogSettings
            {
                Enabled = true,
                PostsPageSize = 10,
                AllowNotRegisteredUsersToLeaveComments = true,
                NotifyAboutNewBlogComments = false,
                NumberOfTags = 15,
                ShowHeaderRssUrl = false,
            });
            settingService.SaveSetting(new NewsSettings
            {
                Enabled = true,
                AllowNotRegisteredUsersToLeaveComments = true,
                NotifyAboutNewNewsComments = false,
                ShowNewsOnMainPage = true,
                MainPageNewsCount = 3,
                NewsArchivePageSize = 10,
                ShowHeaderRssUrl = false,
            });
                       

            var eaGeneral = _emailAccountRepository.Table.FirstOrDefault();
            if (eaGeneral == null)
                throw new Exception("Default email account cannot be loaded");
            settingService.SaveSetting(new EmailAccountSettings
            {
                DefaultEmailAccountId = eaGeneral.Id
            });

            settingService.SaveSetting(new WidgetSettings
            {
                ActiveWidgetSystemNames = new List<string> { "Widgets.NivoSlider" },
            });
        }

        protected virtual void InstallBlogPosts(string defaultUserEmail)
        {
            var defaultLanguage = _languageRepository.Table.FirstOrDefault();
            var blogPosts = new List<BlogPost>
                                {
                                    new BlogPost
                                        {
                                             AllowComments = true,
                                             Language = defaultLanguage,
                                             Title = "巨人快速开发框架介绍",
                                             BodyOverview = "<p></p>",
                                             Body = "<p></p>",
                                             Tags = "快速开发框架, 文档, 介绍",
                                             CreatedOnUtc = DateTime.UtcNow,
                                        },                                   
                                };
            _blogPostRepository.Insert(blogPosts);

            //search engine names
            foreach (var blogPost in blogPosts)
            {
                _urlRecordRepository.Insert(new UrlRecord
                {
                    EntityId = blogPost.Id,
                    EntityName = "BlogPost",
                    LanguageId = blogPost.LanguageId,
                    IsActive = true,
                    Slug = blogPost.ValidateSeName("", blogPost.Title, true)
                });
            }

            //comments
            var defaultUser = _userRepository.Table.FirstOrDefault(x => x.Email == defaultUserEmail);
            if (defaultUser == null)
                throw new Exception("Cannot load default user");
            foreach (var blogPost in blogPosts)
            {
                blogPost.BlogComments.Add(new BlogComment
                {
                    BlogPostId = blogPost.Id,
                    UserId = defaultUser.Id,
                    CommentText = "This is a sample comment for this blog post",
                    CreatedOnUtc = DateTime.UtcNow
                });
                //update totals
                blogPost.CommentCount = blogPost.BlogComments.Count;

            }
            _blogPostRepository.Update(blogPosts);
        }

        protected virtual void InstallNews(string defaultUserEmail)
        {
            var defaultLanguage = _languageRepository.Table.FirstOrDefault();
            var news = new List<NewsItem>
                                {
                                    new NewsItem
                                    {
                                         AllowComments = true,
                                         Language = defaultLanguage,
                                         Title = "关于巨人快速开发框架",
                                         Short = "",
                                         Full = "",
                                         Published  = true,
                                         CreatedOnUtc = DateTime.UtcNow,
                                    },
                                    new NewsItem
                                    {
                                         AllowComments = true,
                                         Language = defaultLanguage,
                                         Title = "巨人快速开发框架V1.00发布啦",
                                         Short = "",
                                         Full = "",
                                         Published  = true,
                                         CreatedOnUtc = DateTime.UtcNow.AddSeconds(1),
                                    }

                                };
            _newsItemRepository.Insert(news);

            //search engine names
            foreach (var newsItem in news)
            {
                _urlRecordRepository.Insert(new UrlRecord
                {
                    EntityId = newsItem.Id,
                    EntityName = "NewsItem",
                    LanguageId = newsItem.LanguageId,
                    IsActive = true,
                    Slug = newsItem.ValidateSeName("", newsItem.Title, true)
                });
            }

            //comments
            var defaultUser = _userRepository.Table.FirstOrDefault(x => x.Email == defaultUserEmail);
            if (defaultUser == null)
                throw new Exception("Cannot load default user");
            foreach (var newsItem in news)
            {
                newsItem.NewsComments.Add(new NewsComment
                {
                    NewsItemId = newsItem.Id,
                    UserId = defaultUser.Id,
                    CommentTitle = "Sample comment title",
                    CommentText = "This is a sample comment...",
                    CreatedOnUtc = DateTime.UtcNow
                });
                //update totals
                newsItem.CommentCount = newsItem.NewsComments.Count;

            }
            _newsItemRepository.Update(news);
        }

        protected virtual void InstallActivityLogTypes()
        {
            var activityLogTypes = new List<ActivityLogType>
                                      {
                                          //admin area activities                                         
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "AddNewUser",
                                                  Enabled = true,
                                                  Name = "Add a new user"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "AddNewUserRole",
                                                  Enabled = true,
                                                  Name = "Add a new user role"
                                              },                                         
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "AddNewSetting",
                                                  Enabled = true,
                                                  Name = "Add a new setting"
                                              },                                          
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "AddNewTopic",
                                                  Enabled = true,
                                                  Name = "Add a new topic"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "AddNewWidget",
                                                  Enabled = true,
                                                  Name = "Add a new widget"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "DeleteActivityLog",
                                                  Enabled = true,
                                                  Name = "Delete activity log"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "DeleteUser",
                                                  Enabled = true,
                                                  Name = "Delete a user"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "DeleteUserRole",
                                                  Enabled = true,
                                                  Name = "Delete a user role"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "DeleteSetting",
                                                  Enabled = true,
                                                  Name = "Delete a setting"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "DeleteTopic",
                                                  Enabled = true,
                                                  Name = "Delete a topic"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "DeleteWidget",
                                                  Enabled = true,
                                                  Name = "Delete a widget"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "EditActivityLogTypes",
                                                  Enabled = true,
                                                  Name = "Edit activity log types"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "EditUser",
                                                  Enabled = true,
                                                  Name = "Edit a user"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "EditUserRole",
                                                  Enabled = true,
                                                  Name = "Edit a user role"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "EditSettings",
                                                  Enabled = true,
                                                  Name = "Edit setting(s)"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "EditTopic",
                                                  Enabled = true,
                                                  Name = "Edit a topic"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "EditWidget",
                                                  Enabled = true,
                                                  Name = "Edit a widget"
                                              },
                                              //public site activities  
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "PublicSite.ContactUs",
                                                  Enabled = false,
                                                  Name = "Public site. Use contact us form"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "PublicSite.Login",
                                                  Enabled = false,
                                                  Name = "Public site. Login"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "PublicSite.Logout",
                                                  Enabled = false,
                                                  Name = "Public site. Logout"
                                              },
                                          new ActivityLogType
                                              {
                                                  SystemKeyword = "PublicSite.AddBlogComment",
                                                  Enabled = false,
                                                  Name = "Public store. Add blog comment"
                                              },
                                      };
            _activityLogTypeRepository.Insert(activityLogTypes);
        }

        protected virtual void InstallTopicTemplates()
        {
            var topicTemplates = new List<TopicTemplate>
                               {
                                   new TopicTemplate
                                       {
                                           Name = "Default template",
                                           ViewPath = "TopicDetails",
                                           DisplayOrder = 1
                                       },
                               };
            _topicTemplateRepository.Insert(topicTemplates);
        }

        protected virtual void InstallScheduleTasks()
        {
            var tasks = new List<ScheduleTask>
            {
                new ScheduleTask
                {
                    Name = "Send emails",
                    Seconds = 60,
                    Type = "Giant.Services.Messages.QueuedMessagesSendTask, Giant.Services",
                    Enabled = true,
                    StopOnError = false,
                },
                new ScheduleTask
                {
                    Name = "Keep alive",
                    Seconds = 300,
                    Type = "Giant.Services.Common.KeepAliveTask, Giant.Services",
                    Enabled = true,
                    StopOnError = false,
                },
                new ScheduleTask
                {
                    Name = "Delete guests",
                    Seconds = 600,
                    Type = "Giant.Services.Users.DeleteGuestsTask, Giant.Services",
                    Enabled = true,
                    StopOnError = false,
                },
                new ScheduleTask
                {
                    Name = "Clear cache",
                    Seconds = 600,
                    Type = "Giant.Services.Caching.ClearCacheTask, Giant.Services",
                    Enabled = false,
                    StopOnError = false,
                },
                new ScheduleTask
                {
                    Name = "Clear log",
                    //60 minutes
                    Seconds = 3600,
                    Type = "Giant.Services.Logging.ClearLogTask, Giant.Services",
                    Enabled = false,
                    StopOnError = false,
                }
            };

            _scheduleTaskRepository.Insert(tasks);
        }

        #endregion

        #region Methods

        public virtual void InstallData(string defaultUserEmail,
            string defaultUserPassword, bool installSampleData = true)
        {
            InstallSites();
         
            InstallLanguages();
            InstallUsersAndUsers(defaultUserEmail, defaultUserPassword);
            InstallEmailAccounts();
            InstallMessageTemplates();
            InstallSettings();
            InstallTopicTemplates();
            InstallTopics();
            InstallLocaleResources();
            InstallActivityLogTypes();
            HashDefaultUserPassword(defaultUserEmail, defaultUserPassword);
            InstallScheduleTasks();

            if (installSampleData)
            {
                InstallBlogPosts(defaultUserEmail);
                InstallNews(defaultUserEmail);
            }
        }

        #endregion
    }
}